home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Applications / FlyThrough 1.1.2 / src / Source / Q3Utilities.cp < prev    next >
Encoding:
Text File  |  1997-03-10  |  4.8 KB  |  149 lines  |  [TEXT/CWIE]

  1. //
  2. //    Q3Utilities.cp
  3. //
  4. //    A bunch of handy QD3D utilites, mostly math.
  5. //    These are written as if they were natural extensions of the QD3D API.
  6. //
  7. //    by James Jennings
  8. //    March 9, 1997
  9. //
  10.  
  11. #include "Q3Utilities.h"
  12.  
  13. TQ3Boolean Q3::Vector3D_Parallel( const TQ3Vector3D *v1, const TQ3Vector3D *v2 )
  14. {
  15.     // Return kQ3True if v1 and v2 are parallel.
  16.     // also if either are null.
  17.     TQ3Vector3D u;
  18.     ::Q3Vector3D_Cross( v1, v2, &u );
  19.     return (::Q3Vector3D_Length( &u ) <= kQ3RealZero) ? kQ3True : kQ3False;
  20. }
  21.  
  22. TQ3Boolean Q3::Vector3D_Orthogonal( const TQ3Vector3D *v1, const TQ3Vector3D *v2 )
  23. {
  24.     // Return kQ3True if v1 and v2 are orthogonal.
  25.     // also if either are null.
  26.     return ( ::Q3Vector3D_Dot( v1, v2 ) <= kQ3RealZero ) ? kQ3True : kQ3False;
  27. }
  28.  
  29. TQ3Vector3D * Q3::Vector3D_MakeOrthogonal( 
  30.         const TQ3Vector3D *v1, const TQ3Vector3D *v2, TQ3Vector3D *v3)
  31. {
  32.     // Make v2 orthogonal to v1 and return it in v3
  33.     Assert_( v1!=nil && v2!=nil && v3!=nil );
  34.     Assert_( ::Q3Vector3D_Length(v1) > 0 && ::Q3Vector3D_Length(v2) > 0 );
  35.     Assert_( ! Vector3D_Parallel( v1, v2 ) );
  36.     
  37.     // Since v1, v2, and v3 might point at the same place in memory we store 
  38.     // intermediate results in v until we don't need v1 or v2 any more.
  39.     TQ3Vector3D v;
  40.     
  41.     float dot = ::Q3Vector3D_Dot( v1, v2 );
  42.     if (dot == 0.0) {
  43.         v = *v2;    // already orthogonal
  44.     } else {
  45.         // v3 = v2 - (v1.v2)v1/|v1||v2|
  46.         // Don't assume that v1 and v2 are normalized.
  47.         dot /= ::Q3Vector3D_Length(v1) * ::Q3Vector3D_Length(v2);
  48.         ::Q3Vector3D_Scale( v1, dot, &v );
  49.         ::Q3Vector3D_Subtract( v2, &v, &v );
  50.         Assert_(::Q3Vector3D_Length(&v) > 0 /* v1, v2 must not be parallel */);
  51.     }
  52.     
  53.     ::Q3Vector3D_Normalize( &v, v3 );
  54.     
  55.     return v3;
  56. }
  57.     
  58. TQ3Vector3D * Q3::Vector3D_CompleteBasis( 
  59.         const TQ3Vector3D *v1, const TQ3Vector3D *v2, TQ3Vector3D *v3)
  60. {
  61.     // Make v3 orthogonal to v1 and v2
  62.     Assert_(v1!=nil && v2!=nil && v3!=nil);
  63.     
  64.     TQ3Vector3D v;
  65.     ::Q3Vector3D_Cross( v1, v2, &v );
  66.     Assert_( ::Q3Vector3D_Length( &v ) != 0 );
  67.     
  68.     ::Q3Vector3D_Normalize( &v, v3 );
  69.     
  70.     return v3;
  71. }
  72.     
  73. TQ3CameraPlacement * Q3::CameraPlacement_Transform( 
  74.     const TQ3CameraPlacement *inPlace, const TQ3Matrix4x4 *M, TQ3CameraPlacement *outPlace )
  75. {
  76.     Assert_( inPlace != nil && M != nil && outPlace != nil);
  77.     ::Q3Point3D_Transform( &inPlace->cameraLocation, M, &outPlace->cameraLocation );
  78.     ::Q3Point3D_Transform( &inPlace->pointOfInterest, M, &outPlace->pointOfInterest );
  79.     ::Q3Vector3D_Transform( &inPlace->upVector, M, &outPlace->upVector );
  80. }
  81.  
  82. TQ3Boolean Q3::CameraPlacement_Validate( TQ3CameraPlacement *inPlace )
  83. {
  84.     // Test if the camera placement is reasonable, fixing the upVector if necessary.
  85.     TQ3Vector3D v;
  86.     ::Q3Point3D_Subtract( &inPlace->pointOfInterest, &inPlace->cameraLocation, &v );
  87.     
  88.     if ( ::Q3Vector3D_Length( &v ) <= kQ3RealZero ) return kQ3False;
  89.     if ( ::Q3Vector3D_Length( &inPlace->upVector ) <= kQ3RealZero ) return kQ3False;
  90.     if ( Vector3D_Parallel( &inPlace->upVector, &v ) ) return kQ3False;
  91.     
  92.     Vector3D_MakeOrthogonal( &v, &inPlace->upVector, &inPlace->upVector );
  93.     
  94.     return kQ3True;
  95. }
  96.  
  97.  
  98.  
  99. TQ3Matrix4x4 *    Q3::Transform_SetRotatePlacementToPlacement( 
  100.     TQ3Matrix4x4 *M, const TQ3CameraPlacement *in1, const TQ3CameraPlacement *in2 )
  101. {    
  102.     // Find a transformation that takes in1 to in2 (••• Not well tested •••)
  103.     
  104.     Assert_( M != nil && in1 != nil && in2 != nil );
  105.     TQ3Matrix4x4 t;
  106.     
  107.     // Move to origin
  108.     ::Q3Matrix4x4_SetTranslate( M, 
  109.             - in1->cameraLocation.x, - in1->cameraLocation.y, - in1->cameraLocation.z);
  110.     // Aim
  111.     TQ3Vector3D v1,v2,v3,v4;
  112.     ::Q3Point3D_Subtract(&in1->pointOfInterest, &in1->cameraLocation, &v1);
  113.     ::Q3Point3D_Subtract(&in2->pointOfInterest, &in2->cameraLocation, &v2);
  114.     Assert_(::Q3Vector3D_Length(&v1) != 0 && ::Q3Vector3D_Length(&v2) != 0);
  115.     ::Q3Vector3D_Normalize(&v1, &v1);
  116.     ::Q3Vector3D_Normalize(&v2, &v2);
  117.     if ( ::Q3Vector3D_Dot( &v1, &v2 ) == -1 ) {
  118.         // v1 == -v2 then rotate 180° about an upVector. (Which one? I'm guessing in1.)
  119.         const TQ3Point3D origin = {0,0,0};
  120.         ::Q3Matrix4x4_SetRotateAboutAxis( &t, &origin, &in1->upVector, kQ3Pi );
  121.     } else {
  122.         // Else a vector to vector rotation is well defined.
  123.         ::Q3Matrix4x4_SetRotateVectorToVector( &t, &v1, &v2 );
  124.     }
  125.     ::Q3Matrix4x4_Multiply( M, &t, M );
  126.     
  127.     // Roll
  128.     // Assert: the upVectors are normalized
  129.     v3 = in1->upVector;
  130.     v4 = in2->upVector;
  131.     ::Q3Vector3D_Transform( &v3, &t, &v3 );
  132.     ::Q3Vector3D_Transform( &v4, &t, &v4 );
  133.     if ( ::Q3Vector3D_Dot( &v3, &v4 ) == -1 ) {
  134.         // v1 == -v2 then rotate 180° about the forward direction
  135.         const TQ3Point3D origin = {0,0,0};
  136.         ::Q3Matrix4x4_SetRotateAboutAxis( &t, &origin, &v2, kQ3Pi );
  137.     } else {
  138.         // Else a vector to vector rotation is well defined.
  139.         ::Q3Matrix4x4_SetRotateVectorToVector( &t, &v3, &v4 );
  140.     }
  141.     ::Q3Matrix4x4_Multiply( M, &t, M );
  142.     
  143.     // Move to target
  144.     ::Q3Matrix4x4_SetTranslate( &t, 
  145.             in2->cameraLocation.x, in2->cameraLocation.y, in2->cameraLocation.z);
  146.     ::Q3Matrix4x4_Multiply( M, &t, M );
  147. }
  148.  
  149.